#include "socket.h"
#include "log.h"

#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <iostream>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>

static Logger::ptr lvqiang = LoggerMgr::GetInstance()->GetLogger("lvqiang");

Socket::Socket()
{
    int on = 1;
    m_recvBuf = std::make_shared<Buffer>();
    m_sendBuf = std::make_shared<Buffer>();
    m_fd = socket(AF_INET, SOCK_STREAM, 0);
    setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
}

Socket::Socket(int fd):m_fd(fd)
{
    m_recvBuf = std::make_shared<Buffer>();
    m_sendBuf = std::make_shared<Buffer>();
}

Socket::~Socket()
{
    LOG_INFO(lvqiang) << "socket 被关闭了" << std::endl;
    close(m_fd);
}

int Socket::Bind(const char* ip, int port)
{
    struct sockaddr_in servaddr;
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    inet_pton(AF_INET, ip, &servaddr.sin_addr);
    servaddr.sin_port = htons(port);
    int ret = ::bind(m_fd, (struct sockaddr*)&servaddr, sizeof(servaddr));
    return ret;
}

int Socket::Listen(int que_num)
{
    int ret = ::listen(m_fd, que_num);
    return ret;
}

int Socket::Receive()
{
    char buf[1024];
    int ret = recv(m_fd, buf, 1024, 0);
    if(ret > 0)
    {
        m_recvBuf->Write(buf, ret);
    }
    return ret;
}

int Socket::Send()
{
    int length = m_sendBuf->GetSize();
    char buf[length];
    m_sendBuf->Read(buf, length);
    int ret = send(m_fd, buf, length, 0);
    LOG_INFO(lvqiang) << "发送了" << ret << "长度的数据";
    return ret;
}

int Socket::GetFd() const
{
    return m_fd;
}

Buffer::ptr& Socket::GetRecvBuf()
{
    return m_recvBuf;
}

Buffer::ptr& Socket::GetSendBuf()
{
    return m_sendBuf;
}

//将文件描述符设置为非阻塞
int Socket::SetNonBlocking()
{
    int old_option = fcntl(m_fd, F_GETFL);
    int new_option = old_option | O_NONBLOCK;
    fcntl(m_fd, F_SETFL, new_option);
    return old_option;
}

void Socket::AddToEpoll(int epollfd, bool enable_et)
{
    struct epoll_event event;
    event.data.fd = m_fd;
    event.events = EPOLLIN;
    if(enable_et)
    {
        event.events |= EPOLLET;
    }
    epoll_ctl(epollfd, EPOLL_CTL_ADD, m_fd, &event);
    SetNonBlocking();
}

void Socket::RemoveFromEpoll(int epollfd)
{
    epoll_ctl(epollfd, EPOLL_CTL_DEL, m_fd, nullptr);
}



